home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / mail / newmail3.000 / newmail3 / newmail / newmail.c < prev    next >
C/C++ Source or Header  |  1992-03-21  |  6KB  |  258 lines

  1. /* newmail(1L), check for new, unread, and total mail messages */
  2. /* Steve Creps, October 24, 1988 */
  3. /* Last modified, July 19, 1991 */
  4.  
  5. /****************************************************************/
  6. /* #include standard copyright notice:                */
  7. /* This program copyright Steve Creps on the above date. Do    */
  8. /* pretty much what you want with it; HOWEVER:            */
  9. /*    1) Don't accept any money for it.            */
  10. /*    2) Do leave my notices intact.                */
  11. /*    3) Do document your changes before passing it on.    */
  12. /****************************************************************/
  13.  
  14. #ifndef lint
  15. static char ID[] = "Newmail, version 3.0, (c) 1991 Steve Creps";
  16. #endif
  17.  
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <errno.h>
  21. #include <sys/types.h>
  22. #include <malloc.h>
  23.  
  24. #define Fprintf (void)fprintf
  25. #define Printf (void)printf
  26. #define NEW 1
  27. #define UNREAD 2
  28. #define OLD 3
  29. #define DEF_INTERVAL    30 /* Default sleep time between checks */
  30. #define MIN_INTERVAL    5  /* Min must be > 0 */
  31. #ifdef BSD
  32. #define MAILDIR "/usr/spool/mail"
  33. #define ENV_USER "USER"
  34. #else
  35. #define MAILDIR "/usr/mail"
  36. #define ENV_USER "LOGNAME"
  37. #endif
  38.  
  39. int optn = 0, optt = 0, optv = 1, opti = 0, optd = 0;
  40. int optb = 0;
  41. int ncount, ucount, tcount, old_ncount = -1;
  42. int nextmsg(), type;
  43.  
  44. char *getenv(), *getln();
  45. int getopt();
  46. unsigned int sleep();
  47. void exit();
  48. extern int opterr, optind;
  49. extern char *optarg;
  50. pid_t fork(), getpid();
  51.  
  52. int
  53. main(argc, argv)
  54. int argc;
  55. char *argv[];
  56. {
  57.     char *mailfile;
  58.     int c;
  59.     FILE *mailfp;
  60.     pid_t child_id = 0;
  61.  
  62.     opterr = 0;
  63.     while ((c = getopt(argc, argv, "bdi:nstv")) != EOF) {
  64.         switch (c) {
  65.       case 'b':
  66.         optb = 1;
  67.         break;
  68.  
  69.       case 'd':
  70.         optd = optn = 1;
  71.         opti = DEF_INTERVAL;
  72.         break;
  73.  
  74.       case 'i':
  75.         if ((opti = atoi(optarg)) < MIN_INTERVAL) {
  76.         Fprintf(stderr,
  77.             "newmail: time interval is too small\n");
  78.         exit(-1);
  79.         }
  80.         break;
  81.  
  82.       case 'n':
  83.         optn = 1;
  84.         optt = 0;
  85.         break;
  86.  
  87.       case 's':
  88.         optt = optv = 0;
  89.         break;
  90.  
  91.       case 't':
  92.         optt = 1;
  93.         optn = optv = 0;
  94.         break;
  95.  
  96.       case 'v':
  97.         optv = 1;
  98.         optt = 0;
  99.         break;
  100.  
  101.       case '?':
  102.         Fprintf(stderr, "newmail: invalid option: %s\n",
  103.             argv[optind - 1]);
  104.         exit(-1);
  105.     }
  106.     }
  107.  
  108.     if (argc > optind + 1) {
  109.     Fprintf(stderr, "Usage: newmail [ -b -d -i interval -n -s -t -v ] [ mailbox ]\n");
  110.     exit(-1);
  111.     }
  112.  
  113.     if (optd == 0 || (child_id = fork()) == 0) {
  114.     if (optd && child_id == 0) {
  115.         Printf("newmail daemon started, pid == %d\n", getpid());
  116.     }
  117.  
  118.     if (argc == optind) {
  119.         char *u = getenv(ENV_USER);
  120.         mailfile = (char *)malloc(sizeof(MAILDIR) + sizeof("/") +
  121.                       sizeof(u) + 1);
  122.         (void)sprintf(mailfile, "%s/%s", MAILDIR, u);
  123.     } else {
  124. #ifdef SYSV
  125.       mailfile = strdup(argv[optind]);
  126. #else
  127.       /* No strdup() on Ultrix; sigh.  Don't try to free this below. */
  128.       mailfile = argv[optind];
  129. #endif
  130.     }
  131.  
  132.     do {
  133.         ncount = ucount = tcount = 0;
  134.         if ((mailfp = fopen(mailfile, "r")) == NULL) {
  135.         if (errno != ENOENT || argc > optind) {
  136.             Fprintf(stderr, "newmail: cannot open %s\n",
  137.                 mailfile);
  138.             return -1;
  139.         }
  140.         } else {
  141.         while (type = nextmsg(mailfp)) {
  142.             switch (type) {
  143.               case NEW:
  144.             ncount++;
  145.  
  146.               case UNREAD:
  147.             ucount++;
  148.  
  149.               case OLD:
  150.             tcount++;
  151.             break;
  152.  
  153.               default:
  154.             continue;
  155.             }
  156.         }
  157.         }
  158.  
  159.         if (ncount > old_ncount) {
  160.         if (optv) {
  161.             if (optb && ncount > 0) putchar(0x07);
  162.             if (tcount == 0) {
  163.             if (!optn) Printf("%s: no messages.\n",
  164.                       mailfile);
  165.             } else {
  166.             Printf("%s: ", mailfile);
  167.             if (ncount) Printf("%d new, ", ncount);
  168.             if (ucount && ucount != ncount) 
  169.                 Printf("%d unread, ", ucount);
  170.             Printf("%d message%s total.\n", tcount,
  171.                    tcount > 1 ? "s" : "");
  172.             }
  173.         } else if (optt)
  174.             Printf("%d\t%d\t%d\n", ncount, ucount, tcount);
  175.         }
  176.         old_ncount = ncount;
  177.         (void)fclose(mailfp);
  178. #ifdef BSD
  179.         if (opti > 0) (void)sleep((unsigned)opti);
  180. #else
  181.         if (opti > 0) (void)sleep((unsigned long)opti);
  182. #endif
  183.     } while (opti > 0);
  184.     }
  185. #ifdef SYSV
  186.     /* Just to be neat.  See comment after strdup() above. */
  187.     free((void *)mailfile);
  188. #endif
  189.  
  190.     return optd > 0 ? child_id : ncount;
  191. }
  192.  
  193. #define MAXLEN 12 /* we're discarding most of the end of the line */
  194. static char line[MAXLEN] = NULL;
  195.  
  196. int
  197. nextmsg(fp)
  198. FILE *fp;
  199. {
  200.     int mtype = NEW, past_header = 0;
  201.     while (strncmp(line, "From ", 5) != 0)
  202.     if (getln(fp, line, MAXLEN) == NULL) return 0;
  203.     do {
  204.     if (strlen(line) == 1) {
  205.         past_header++;
  206.         while (strlen(line) == 1)
  207.         (void)getln(fp, line, MAXLEN);
  208.         if (strncmp(line, "From ", 5) == 0) {
  209.         return mtype;
  210.         }
  211.     }
  212.     if (strncmp(line, "Status: O", 9) == 0) {
  213.         if (!past_header) mtype = UNREAD;
  214.         continue;
  215.     }
  216.     if (strncmp(line, "Status: RO", 10) == 0) {
  217.         if (!past_header) mtype = OLD;
  218.         continue;
  219.     }
  220.     } while (getln(fp, line, MAXLEN));
  221.  
  222.     return mtype;
  223. }
  224.  
  225. /* Read a line from given stream, return in line. If line is too */
  226. /* long, truncate and read past next \n. Terminate with (char)0. */
  227. char *
  228. getln(fp, msgline, maxlen)
  229. FILE *fp;
  230. char msgline[];
  231. int maxlen;
  232. {
  233.     int i, maxc = maxlen - 2;
  234.     char c;
  235.     for (i = 0; i < maxc && (msgline[i] = getc(fp)) != '\n'; i++) {
  236.     if ((int)msgline[i] == EOF) {
  237.         msgline[0] = (char)0;
  238.         return NULL;
  239.     }
  240.     }
  241.  
  242.     if (i == maxc) {
  243.     msgline[maxc++] = '\n';
  244.     msgline[maxc] = (char)0;
  245.     while ((c = getc(fp)) != '\n') {
  246.         if ((int)c == EOF) {
  247.         msgline[0] = (char)0;
  248.         return NULL;
  249.         }
  250.     }
  251.     } else {
  252.     msgline[i++] = '\n';
  253.     msgline[i] = (char)0;
  254.     }
  255.  
  256.     return msgline;
  257. }
  258.